/**
 * Defines the possible data types encountered during serialization.
 */
export type UniversalDataType =
  | 'Undefined'
  | 'Null'
  | 'String'
  | 'Number'
  | 'Boolean'
  | 'BigInt'
  | 'Symbol'
  | 'Date'
  | 'RegExp'
  | 'Array'
  | 'Object'
  | 'Map'
  | 'Set'
  | 'WeakMap'       // Represents presence, no content serialized
  | 'WeakSet'       // Represents presence, no content serialized
  | 'Function'      // Represents presence, source code included
  | 'Error'         // Represents an Error object
  | 'ArrayBuffer'   // Represents ArrayBuffer data (using Base64)
  | 'TypedArray'    // Represents TypedArray data (using Base64)
  | 'CircularRef';  // Marker for a previously seen object/array/etc.

/**
 * Base interface for tagged intermediate representation objects.
 * Contains the original data type and an optional ID for cycle tracking.
 */
interface UniversalBaseIR {
  __universalDataType__: UniversalDataType;
  __universalRefId__?: number; // Optional: Assigned to objects/arrays/functions etc. that might be targets of cycles
}

// --- Specific IR Interfaces ---

export interface UniversalUndefinedIR extends UniversalBaseIR { __universalDataType__: 'Undefined'; }
export interface UniversalNullIR extends UniversalBaseIR { __universalDataType__: 'Null'; }
export interface UniversalBigIntIR extends UniversalBaseIR { __universalDataType__: 'BigInt'; value: string; } // Store as string
export interface UniversalSymbolIR extends UniversalBaseIR { __universalDataType__: 'Symbol'; description: string | undefined; }
export interface UniversalDateIR extends UniversalBaseIR { __universalDataType__: 'Date'; value: string; } // Store as ISO string
export interface UniversalRegExpIR extends UniversalBaseIR { __universalDataType__: 'RegExp'; source: string; flags: string; }
export interface UniversalFunctionIR extends UniversalBaseIR { __universalDataType__: 'Function'; source: string; } // Store source code
export interface UniversalErrorIR extends UniversalBaseIR {
  __universalDataType__: 'Error';
  name: string;
  message: string;
  stack?: string;
  cause?: any; // Cause will be recursively serialized into its IR form
}
export interface UniversalWeakMapIR extends UniversalBaseIR { __universalDataType__: 'WeakMap'; } // Marker only
export interface UniversalWeakSetIR extends UniversalBaseIR { __universalDataType__: 'WeakSet'; } // Marker only
export interface UniversalArrayBufferIR extends UniversalBaseIR { __universalDataType__: 'ArrayBuffer'; base64: string; }
export interface UniversalTypedArrayIR extends UniversalBaseIR {
  __universalDataType__: 'TypedArray';
  constructorName: string; // e.g., 'Uint8Array', 'Float32Array'
  base64: string; // Base64 representation of the underlying buffer
}

export interface UniversalArrayIR extends UniversalBaseIR {
  __universalDataType__: 'Array';
  values: UniversalIR[]; // Array of recursively serialized items
}

export type UniversalObjectKeyIR = string | UniversalSymbolIR; // Object keys can be strings or serialized Symbols
export type UniversalObjectEntry = [UniversalObjectKeyIR, UniversalIR]; // [Key IR, Value IR] pair

export interface UniversalObjectIR extends UniversalBaseIR {
  __universalDataType__: 'Object';
  // className?: string; // Optional: Store constructor name for non-plain objects
  entries: UniversalObjectEntry[]; // Array of [keyIR, valueIR] pairs, capturing all own keys (string & symbol)
}

export interface UniversalMapIR extends UniversalBaseIR {
  __universalDataType__: 'Map';
  entries: [UniversalIR, UniversalIR][]; // Array of [serialized key IR, serialized value IR] pairs
}

export interface UniversalSetIR extends UniversalBaseIR {
  __universalDataType__: 'Set';
  values: UniversalIR[]; // Array of recursively serialized values
}

export interface UniversalCircularRefIR {
  // No UniversalBaseIR needed, this *is* the reference
  __universalDataType__: 'CircularRef';
  __universalRefId__: number; // The ID of the object/array/etc. being referenced
}

/**
 * Union type representing any possible structure within the Intermediate Representation.
 * It can be a tagged object defined above, or a standard JSON primitive.
 */
export type UniversalIR =
  | UniversalUndefinedIR | UniversalNullIR | UniversalBigIntIR | UniversalSymbolIR
  | UniversalDateIR | UniversalRegExpIR | UniversalFunctionIR | UniversalErrorIR
  | UniversalWeakMapIR | UniversalWeakSetIR | UniversalArrayBufferIR | UniversalTypedArrayIR
  | UniversalArrayIR | UniversalObjectIR | UniversalMapIR | UniversalSetIR
  | UniversalCircularRefIR
  | string | number | boolean | null; // Include standard JSON primitives

/**
 * Wrapper interface for when the entire QuickJS execution results in an error.
 */
export interface UniversalExecutionErrorWrapper {
    __universalExecutionError__: UniversalErrorIR | UniversalIR; // Contains the serialized error object
} 